from datetime import datetime
import json
import os.path
import re
import time
from typing import Tuple
import unicodedata
from urllib.parse import urljoin
from urllib.parse import urlparse, urlsplit
# base_url = "http://www.example.com/path/"
# relative_url = "subpath/file.html"
# full_url = urljoin(base_url, relative_url)


def build_url(org_url: str, href_url: str):

    if href_url.startswith("http"):
        return href_url

    full_url = urljoin(org_url, href_url)
    return full_url


# import json
#
# jsonl_file = "scrapyd.jsonl"
#
# with open(jsonl_file, "r") as file:
#     for line in file:
#         json_obj = json.loads(line)
#         # 对 JSON 对象进行处理
#         print(json_obj["name"], json_obj["age"])
#获取json文件中的items,根据fields字段，返回items列表
def get_json_items(file_path: str, ignore_callback=None, fields=[]):
    items = []
    urls = []
    # file_path = "J:/developer/ScrapyDemo/jiaoyubu/jiaoyubu/jiaoyubu_filelist.json"

    _, fextension = os.path.splitext(file_path)

    with open(file_path, encoding='utf-8', mode='r') as f:
        if fextension == '.json':
            contents = json.load(f)
            for content in contents:
                # print(content["url"])
                if ignore_callback and ignore_callback(content):
                    continue
                urls.append(content["url"]) if "url" in content else ""
                item = []
                for field in fields:
                    if field in content:
                        item.append({field: content[field]})
                items.append(item)

        elif (fextension == '.jsonl'):
            for line in f:
                content = json.loads(line)
                # 对 JSON 对象进行处理
                # print(content["url"])
                if ignore_callback and ignore_callback(content):
                    continue
                urls.append(content["url"]) if "url" in content else ""
                item = []
                for field in fields:
                    if field in content:
                        item.append({field: content[field]})
                items.append(item)

    return urls, items


def get_affix(file_path: str, ignore_callback=None):
    affix_urls = []
    # file_path = "J:/developer/ScrapyDemo/jiaoyubu/jiaoyubu/jiaoyubu_filelist.json"
    with open(file_path, encoding='utf-8', mode='r') as f:
        contents = json.load(f)
        for content in contents:
            # print(content["url"])
            if ignore_callback and ignore_callback(content):
                continue
            affix_url = content.get("affix_url") if content.get(
                "affix_url") else ""
            if affix_url != "":
                affix_urls.append(content["affix_url"])

    return affix_urls


def is_support_suffix(url):
    affixs_url_suffix = [
        'doc', 'docx', 'xls', 'xlsx', 'wps', 'zip', 'rar', 'pdf', 'txt', 'ppt',
        'jpg'
    ]
    suffix = get_url_suffix(url)
    if suffix in affixs_url_suffix:
        return True
    else:
        return False


# def get_str_md5(inStr):
#     import md5
#     m1 = md5.new()
#     m1.update(inStr)
#     return m1.hexdigest()


def get_str_md5(s):
    import hashlib
    """计算字符串的 MD5 值"""
    return hashlib.md5(s.encode('utf-8')).hexdigest()


def get_url_suffix(url):
    # 解析URL
    parsed_url = urlsplit(url)
    # 获取路径部分
    path = parsed_url.path
    # 从路径中提取文件名
    filename = path.split('/')[-1]
    # 提取文件扩展名
    suffix = filename.split('.')[-1]
    return suffix


def format_str(input_string):
    if input_string:
        if len(input_string) > 0:
            normalized_string = unicodedata.normalize('NFKC', input_string)
            formatted_string = normalized_string.strip()  # 删除开头和结尾的不可见字符
            return formatted_string
        else:
            return ""
    else:
        return ""


def _convert_cn_num(cn_str: str) -> str:
    """将中文数字转换为阿拉伯数字"""
    CN_NUM = {
        '○': '0',
        '〇': '0',
        '零': '0',
        '一': '1',
        '壹': '1',
        '二': '2',
        '贰': '2',
        '两': '2',
        '三': '3',
        '叁': '3',
        '四': '4',
        '肆': '4',
        '五': '5',
        '伍': '5',
        '六': '6',
        '陆': '6',
        '七': '7',
        '柒': '7',
        '八': '8',
        '捌': '8',
        '九': '9',
        '玖': '9',
        '十': '10',
        '拾': '10'
    }

    # 如果全是数字，直接返回
    if cn_str.isdigit():
        return cn_str

    # 如果输入的字符不在映射表中且不是数字，抛出KeyError
    for char in cn_str:
        if not char.isdigit() and char not in CN_NUM and char not in ['年', '月', '日']:
            raise KeyError(f"无效的中文数字: {char}")

    # 处理"十"的特殊情况
    if cn_str == '十' or cn_str == '拾':
        return '10'

    # 处理带"十"的数字
    if '十' in cn_str or '拾' in cn_str:
        # 处理十几
        if len(cn_str) == 2 and (cn_str.endswith('十') or cn_str.endswith('拾')):
            return str(int(CN_NUM[cn_str[0]]) * 10)
        # 处理几十
        if len(cn_str) == 2 and (cn_str.startswith('十') or cn_str.startswith('拾')):
            return str(10 + int(CN_NUM[cn_str[1]]))
        # 处理几十几
        if len(cn_str) == 3:
            first = cn_str[0]
            last = cn_str[2]
            if first in CN_NUM and last in CN_NUM:
                return str(int(CN_NUM[first]) * 10 + int(CN_NUM[last]))

    # 处理普通数字（包括阿拉伯数字）
    result = ''
    for char in cn_str:
        if char.isdigit():
            result += char
        elif char in CN_NUM:
            result += CN_NUM[char]

    return result


def is_valid_date(date_str: str) -> Tuple[bool, str]:
    """检查字符串是否为有效的日期格式，并返回标准化的日期字符串YYYY-MM-DD
    
    Args:
        date_str: 输入的日期字符串
        
    Returns:
        tuple: (是否有效的日期, 标准化后的日期字符串YYYY-MM-DD)
        如果日期无效，返回(False, "")
    """
    if not date_str or not isinstance(date_str, str):
        return False, ""

    # 去除空格
    date_str = date_str.strip()
    date_str = date_str.replace(" ", "")

    # 检查字符串长度是否在合理范围内
    # 最短的合法格式如："2022-1-1"，长度为8
    # 最长的合法格式如："二〇二二年十二月三十一日"，长度为15
    if len(date_str) < 8 or len(date_str) > 15:
        return False, ""

    # 检查混合中文和阿拉伯数字格式
    if re.match(
            r'^[二○〇零一两三四五六七八九十0-9]{4}年[一二三四五六七八九十0-9]{1,3}月[一二三四五六七八九十0-9]{1,3}日$',
            date_str):
        try:
            # 分别提取年月日
            year = re.search(r'^([二○〇零一两三四五六七八九十0-9]{4})年', date_str).group(1)
            month = re.search(r'年([一二三四五六七八九十0-9]{1,3})月', date_str).group(1)
            day = re.search(r'月([一二三四五六七八九十0-9]{1,3})日$', date_str).group(1)

            # 处理混合数字的情况
            def convert_mixed_num(num_str):
                try:
                    # 如果全是数字，直接返回
                    if num_str.isdigit():
                        return True, num_str
                    # 否则使用中文数字转换
                    converted = _convert_cn_num(num_str)
                    return True, converted
                except (ValueError, KeyError):
                    return False, ""

            # 转换年月日
            success_year, year_str = convert_mixed_num(year)
            success_month, month_str = convert_mixed_num(month)
            success_day, day_str = convert_mixed_num(day)

            if not (success_year and success_month and success_day):
                return False, ""

            # 转换为标准格式，确保月份和日期是两位数
            date_obj = datetime.strptime(f"{year_str}-{month_str}-{day_str}", '%Y-%m-%d')
            return True, date_obj.strftime('%Y-%m-%d')
        except (ValueError, AttributeError, KeyError):
            return False, ""

    # 检查标准格式 (YYYY-MM-DD)
    if re.match(r'^\d{4}-\d{1,2}-\d{1,2}$', date_str):
        try:
            date_obj = datetime.strptime(date_str, '%Y-%m-%d')
            return True, date_obj.strftime('%Y-%m-%d')
        except ValueError:
            return False, ""

    # 检查普通中文格式 (YYYY年MM月DD日)
    if re.match(r'^\d{4}年\d{1,2}月\d{1,2}日$', date_str):
        try:
            date_obj = datetime.strptime(date_str, '%Y年%m月%d日')
            return True, date_obj.strftime('%Y-%m-%d')
        except ValueError:
            return False, ""

    # 检查其他格式 (YYYY/MM/DD, YYYY.MM.DD)
    date_patterns = ['%Y/%m/%d', '%Y.%m.%d']

    for pattern in date_patterns:
        try:
            date_obj = datetime.strptime(date_str, pattern)
            return True, date_obj.strftime('%Y-%m-%d')
        except ValueError:
            continue

    return False, ""


def test_is_valid_date():
    # 测试标准日期格式
    assert is_valid_date("2024-01-01") == (True, "2024-01-01")
    assert is_valid_date("2024/01/01") == (True, "2024-01-01")
    assert is_valid_date("2024.01.01") == (True, "2024-01-01")

    # 测试中文日期格式
    assert is_valid_date("2024年01月01日") == (True, "2024-01-01")
    assert is_valid_date("2024年1月1日") == (True, "2024-01-01")

    # 测试混合中文数字格式
    assert is_valid_date("二〇二〇年二月二十九日") == (True, "2020-02-29")
    assert is_valid_date("二00二年十月三十一日") == (True, "2002-10-31")

    # 测试无效日期
    assert is_valid_date("2022-13-45") == (False, "")
    assert is_valid_date("二〇二二年二月三十日") == (False, "")  # 2月没有30日
    assert is_valid_date("") == (False, "")
    assert is_valid_date(None) == (False, "")


def format_date(date_str: str) -> str:
    """
    格式化日期字符串为标准格式 (YYYY-MM-DD)
    如果无法格式化则返回原字符串
    
    Args:
        date_str: 原始日期字符串
        
    Returns:
        str: 格式化后的日期字符串
    """
    if not date_str or not isinstance(date_str, str):
        return date_str

    # 常见的日期格式模式
    date_patterns = ['%Y-%m-%d', '%Y/%m/%d', '%Y.%m.%d', '%Y年%m月%d日']

    date_str = date_str.strip()
    for pattern in date_patterns:
        try:
            date_obj = datetime.strptime(date_str, pattern)
            return date_obj.strftime('%Y-%m-%d')
        except ValueError:
            continue

    return date_str


if __name__ == '__main__':
    # file ="/home/jhq/work/code/crawl/eduCrawl/mycrawl/export_data/example/2024-12-18/example_001.jsonl"
    # print(get_urls(file))
    # pass
    # href = build_url("http://www.moe.gov.cn/jyb_sjzl/s3165/index_15.html","./202006/t20200629_469086.html")
    # print(href)
    # urls = ["https://pzjh.chsi.com.cn", "http://www.moe.gov.cn/ewebeditor/uploadfile/2015/03/23/20150323102701920.doc"]
    # for url in urls:
    #     print(is_support_suffix(url))

    # md5_str = get_str_md5('\n    述职报告\n  ", "url": "50')
    # print(md5_str)
    test_is_valid_date()
    # _convert_cn_num('')
    pass


def test_format_str():
    # 测试普通字符串
    assert format_str("  Hello World  ") == "Hello World"

    # 测试空字符串
    assert format_str("") == ""

    # 测试None值
    assert format_str(None) == ""

    # 测试全角字符
    assert format_str("　你好世界　") == "你好世界"

    # 测试特殊Unicode字符
    assert format_str("\u3000测试\u3000") == "测试"

    # 测试混合字符
    assert format_str(" 　Hello　世界 ") == "Hello 世界"

    print("所有format_str测试用例通过!")


def is_spider_debug():
    is_dbg = os.getenv("SPIDER_DEBUG", False)
    if isinstance(is_dbg, str):
        if is_dbg == "True":
            return True
        else:
            return False
    else:
        # comment: 如果是其他类型的值则返回False
        return is_dbg


if __name__ == '__main__':
# 方法1: 使用字典语法
    # os.environ["SPIDER_DEBUG"] = "True"
    # print(is_spider_debug())

    pass